package edu.kufpg.armatus.console;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.ActionMode.Callback;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ListView;
import edu.kufpg.armatus.R;
import edu.kufpg.armatus.activity.ConsoleEntryIntent;
import edu.kufpg.armatus.activity.ConsoleEntryScopeActivity;
import edu.kufpg.armatus.activity.ConsoleEntrySelectionActivity;
import edu.kufpg.armatus.activity.ConsoleEntrySelectionActivity2;
import edu.kufpg.armatus.util.ParcelUtils;
import edu.kufpg.armatus.util.StringUtils;
import edu.kufpg.armatus.util.Views;
import java.util.SortedSet;
import java.util.TreeSet;
public class ConsoleListView extends ExpandableListView {
private ConsoleActivity mConsole;
private ActionMode mActionMode;
private ConsoleListViewCallback2 mActionModeCallback;
private boolean mActionModeVisible = false;
private SortedSet<Integer> mPrevCheckedStates = new TreeSet<Integer>();
public ConsoleListView(Context context) {
super(context);
init(context);
}
public ConsoleListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public ConsoleListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
mConsole = (ConsoleActivity) context;
mActionModeCallback = new ConsoleListViewCallback2(mConsole, this);
setGroupIndicator(null);
setOnGroupClickListener(new OnGroupClickListener() { // Disable collapsing of groups
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
return true;
}
});
setOnChildClickListener(new OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
boolean showActionMode = true;
int combinedChildId = Views.getFlatListPosition(ConsoleListView.this, groupPosition, childPosition);
//int combinedChildId = getFlatListPosition(getPackedPositionForChild(groupPosition, childPosition));
setItemChecked(combinedChildId, !mPrevCheckedStates.contains(combinedChildId));
if (mPrevCheckedStates.contains(combinedChildId)) {
mPrevCheckedStates.remove(combinedChildId);
} else {
mPrevCheckedStates.add(combinedChildId);
}
if (mPrevCheckedStates.isEmpty()) {
showActionMode = false;
}
setActionModeVisible(showActionMode);
refreshActionMode();
return true;
}
});
}
public boolean isActionModeVisible() {
return mActionModeVisible;
}
/**
* Shows or hides the {@link ListView}'s {@link ActionMode}.
* @param visible {@code true} if the {@code ActionMode} should be shown,
* {@code false} if it should be hidden.
*/
public void setActionModeVisible(boolean visible) {
if (visible && !mActionModeVisible) {
mActionMode = startActionMode(mActionModeCallback);
} else if (!visible && mActionModeVisible) {
mActionMode.finish();
}
}
private void refreshActionMode() {
if (isActionModeVisible()) {
updateSinglyClickedActionModeItems(mPrevCheckedStates.size());
}
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.checkedStates = mPrevCheckedStates;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
}
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
mPrevCheckedStates = ss.checkedStates;
if (!mPrevCheckedStates.isEmpty()) {
setActionModeVisible(true);
for (int item : mPrevCheckedStates) {
setItemChecked(item, true);
}
}
refreshActionMode();
}
protected SortedSet<Integer> getPrevCheckedStates() {
return mPrevCheckedStates;
}
void setActionModeVisibleInternal(boolean visible) {
mActionModeVisible = visible;
}
void updateSinglyClickedActionModeItems(int itemsSelected) {
boolean oneSelected = itemsSelected == 1;
mActionMode.setSubtitle(oneSelected ? "One entry selected" : itemsSelected + " entries selected");
mActionModeCallback.setSinglyClickedItemVisibility(oneSelected);
}
@Override
public void setAdapter(ExpandableListAdapter adapter) {
super.setAdapter(adapter);
expandAllGroups();
}
public void expandAllGroups() {
for (int i = 0; i < getExpandableListAdapter().getGroupCount(); i++) {
expandGroup(i);
}
}
protected static class ConsoleListViewCallback2 implements Callback {
private ConsoleActivity mConsole;
private ConsoleListView mListView;
private MenuItem mSwapItem, mTransformItem, mTransform2Item;
public ConsoleListViewCallback2(ConsoleActivity console, ConsoleListView listView) {
mConsole = console;
mListView = listView;
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.console_list_view_action_mode, menu);
mode.setTitle("Select entries");
mSwapItem = menu.findItem(R.id.console_list_view_swap);
mTransformItem = menu.findItem(R.id.console_list_view_transform);
mTransform2Item = menu.findItem(R.id.console_list_view_transform2);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
mListView.setActionModeVisibleInternal(true);
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
final SortedSet<Integer> prevCheckedStates = mListView.getPrevCheckedStates();
switch (item.getItemId()) {
case R.id.console_list_view_copy:
StringBuilder copyBuilder = new StringBuilder();
for (int state : prevCheckedStates) {
int groupPos = Views.getGroupPosition(mListView, state);
copyBuilder.append(mConsole.getEntry(groupPos)
.getFullContents()).append('\n');
}
copyBuilder.deleteCharAt(copyBuilder.length() - 1); //Remove final newline
ClipboardManager clipboard = (ClipboardManager) mConsole.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData copiedText = ClipData.newPlainText("copiedText",
StringUtils.noCharWrap(copyBuilder.toString()));
clipboard.setPrimaryClip(copiedText);
mConsole.showToast((prevCheckedStates.size() == 1 ? "Entry" : "Entries") + " copied to clipboard!");
mode.finish();
return true;
case R.id.console_list_view_select:
SortedSet<ConsoleLineParams> lineParams = new TreeSet<ConsoleLineParams>();
for (int state : prevCheckedStates) {
int groupPos = Views.getGroupPosition(mListView, state);
int childPos = Views.getChildPosition(mListView, state);
lineParams.add(new ConsoleLineParams(groupPos, childPos));
}
mConsole.showEntrySelectionDialog(lineParams);
mode.finish();
return true;
case R.id.console_list_view_swap:
if (prevCheckedStates.size() == 1) {
int selState = prevCheckedStates.first();
int groupPos = Views.getGroupPosition(mListView, selState);
ConsoleEntry entry = mConsole.getEntry(groupPos);
if (entry.getShortContents().toString().split(StringUtils.WHITESPACE).length > 1) {
mConsole.showKeywordSwapDialog(entry.getEntryNum(), entry.getShortContents().toString());
}
mode.finish();
}
return true;
case R.id.console_list_view_transform:
if (prevCheckedStates.size() == 1) {
int selState = prevCheckedStates.first();
int groupPos = Views.getGroupPosition(mListView, selState);
ConsoleEntry entry = mConsole.getEntry(groupPos);
if (entry.getCommandResponse() != null && entry.getCommandResponse().getGlyphs() != null) {
Intent intent = new ConsoleEntryIntent(entry, mConsole, ConsoleEntrySelectionActivity.class);
mConsole.startActivity(intent);
}
mode.finish();
}
return true;
case R.id.console_list_view_transform2:
if (prevCheckedStates.size() == 1) {
int selState = prevCheckedStates.first();
int groupPos = Views.getGroupPosition(mListView, selState);
ConsoleEntry entry = mConsole.getEntry(groupPos);
if (entry.getCommandResponse() != null && entry.getCommandResponse().getGlyphs() != null) {
Intent intent = new ConsoleEntryIntent(entry, mConsole, ConsoleEntrySelectionActivity2.class);
mConsole.startActivity(intent);
}
mode.finish();
}
return true;
case R.id.console_list_view_scope: {
if (prevCheckedStates.size() == 1) {
int selState = prevCheckedStates.first();
int groupPos = Views.getGroupPosition(mListView, selState);
ConsoleEntry entry = mConsole.getEntry(groupPos);
Intent scopeIntent = new ConsoleEntryIntent(entry, mConsole, ConsoleEntryScopeActivity.class);
mConsole.startActivity(scopeIntent);
mode.finish();
}
return true;
}
}
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
mListView.clearChoices();
mListView.requestLayout();
mListView.getPrevCheckedStates().clear();
mListView.setActionModeVisibleInternal(false);
}
public void setSinglyClickedItemVisibility(boolean visible) {
mSwapItem.setVisible(visible);
mTransformItem.setVisible(visible);
mTransform2Item.setVisible(visible);
}
}
protected static class SavedState extends BaseSavedState {
SortedSet<Integer> checkedStates;
SavedState(Parcelable superState) {
super(superState);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
ParcelUtils.writeCollection(dest, checkedStates);
}
public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
private SavedState(Parcel in) {
super(in);
checkedStates = ParcelUtils.readTreeSet(in);
}
}
}